package com.msoe.server;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.msoe.client.MSOERServer;
import com.msoe.client.dataaccess.SimpleUser;
import com.msoe.core.database.RideDatabase;
import com.msoe.core.database.UserDatabase;
import com.msoe.core.ride.Location;
import com.msoe.core.ride.Ride;
import com.msoe.core.users.AccountType;
import com.msoe.core.users.Password;
import com.msoe.core.users.SaltedHash;
import com.msoe.core.users.User;
import com.msoe.utils.Emailer;

public class MSOERServerImpl extends RemoteServiceServlet implements MSOERServer
{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6490144009271518725L;

	public boolean addUser(String username, String fname, String lname, String email) 
	{
		//TODO: No error handling for database constraints
		boolean retValue = false;
		String password = randomstring(5,8);
		
		try
		{
			SaltedHash sh = SaltedHash.create(password);
			UserDatabase.getInstance().addUser(new User(-1, fname, lname, new Password(sh.getSalt(), sh.getHash()), username, AccountType.Standard, email));
			
			retValue = true;
		}
		catch(Exception e)
		{
			System.out.println("Error adding user: " + e.getMessage());
		}
		
		//Only email the user if it was successfully added to the database
		if(retValue){
			Emailer emailer = new Emailer();
			retValue = emailer.sendNewUserMessage(email, username, password);
		}
		
		return retValue;
	}
	
	public boolean addRide(String username, String LatStart, String LngStart, String LatEnd,String LngEnd,String timeLeavingStr, int numSeats)
	{
		
		SimpleDateFormat sdf = new SimpleDateFormat();
		
		//default to current time
		long timeLeaving = GregorianCalendar.getInstance().getTimeInMillis();
		
		//try to parse pass in time
		try
		{
			Date date = sdf.parse(timeLeavingStr);
			timeLeaving = date.getTime();
		}
		catch(ParseException e)
		{
			e.printStackTrace();
		}
		
		//add a ride to the database
		RideDatabase.getInstance().addRide(new Ride(UserDatabase.getInstance().getUser(username).getUserID(),timeLeaving,new Location(LatStart,LngStart),new Location(LatEnd,LngEnd), numSeats));
		
		return true;
	}

	public SimpleUser authenticateUser(String username, String password) 
	{
		User user = UserDatabase.getInstance().getUser(username);
		
		try 
		{
			SimpleUser toRet = new SimpleUser();
			
			if(user.authenticate(password) != null)
			{
				toRet.email = user.getEmail();
				toRet.firstName = user.getFirstName();
				toRet.lastName = user.getLastName();
				toRet.userid = user.getUserID();
				toRet.username = user.getUsername();
			}
			else toRet = null;
			
			return toRet;
		} 
		catch (Exception e) 
		{
			System.out.println("Error authenticating user: " + e.getMessage());
			return null;
		}
	}

	@Override
	public SimpleUser getUser(int userID)
	{
		return null;		
	}
	
	private String randomstring(int lo, int hi){
        int n = rand(lo, hi);
        char b[] = new char[n];
        for (int i = 0; i < n; i++)
                b[i] = (char)rand('!', '~');
        return new String(b);
	}

	private int rand(int lo, int hi){
        java.util.Random rn = new java.util.Random();
        int n = hi - lo + 1;
        int i = rn.nextInt() % n;
        if (i < 0)
                i = -i;
        return lo + i;
	}

	@Override
	public boolean setVerified(String username, boolean verified)
	{
		return UserDatabase.getInstance().setEmailVerified(UserDatabase.getInstance().getUser(username).getUserID(), verified);
	}

	@Override
	public boolean getBanned(String username)
	{
		return UserDatabase.getInstance().getBannned(UserDatabase.getInstance().getUser(username).getUserID());
	}
	
	public boolean changePassword(String username,String newPassword){
		boolean retVal = true;
		
		try{
			User user = UserDatabase.getInstance().getUser(username);
			SaltedHash sh = SaltedHash.create(newPassword);
			Password pass = new Password(sh.getSalt(), sh.getHash());
			retVal = UserDatabase.getInstance().changePassword(user, pass);
		}
		catch(Exception e){
			System.out.println("Error changing the user's password: " + e.getMessage());
			retVal = false;
		}
		
		return retVal;
	}
}
